#pragma once
//#include "stdafx.h"
#include "BoundedSpace.h"
namespace org
{
	namespace spark
	{
		namespace space
		{
			using org::spark::data::Grid;
			using org::spark::math::RandomHelper;
			using org::spark::math::Vector;

			BoundedSpace::HashGrid2d::HashGrid2d(BoundedSpace *space, int xSize, int ySize) :Grid(space, xSize, ySize)
			{

//ORIGINAL LINE: nodes = new SpaceNode[xSize][ySize];
// NOTE: The following call to the 'RectangularArrays' helper class reproduces the rectangular vector initialization that is automatic in Java:
				nodes = RectangularArrays::ReturnRectangularSpaceNodeArray(xSize, ySize);
				for (int i = 0; i < xSize; i++)
					for (int j = 0; j < ySize; j++)
					{
						CircleNode *p=new CircleNode(space, 0.0);
						nodes[i][j] = dynamic_cast<SpaceNode*>(p);
						nodes[i][j]->next = nodes[i][j]->prev = nodes[i][j];
					}
			}

			SpaceNode *BoundedSpace::HashGrid2d::getNode(int x, int y)
			{
				return nodes[x][y];
			}

			SpaceNode *BoundedSpace::HashGrid2d::getNode(double x, double y)
			{
				int xx = findX(x);
				int yy = findY(y);

				return nodes[xx][yy];
			}

			/*void BoundedSpace::HashGrid2d::verifyIntegrity()
			{
				std::vector<SpaceNode*> list = std::vector<SpaceNode*>(100);

				for (int i = 0; i < xSize; i++)
					for (int j = 0; j < ySize; j++)
					{
						SpaceNode *first = &nodes[i][j];
						if (first == 0 || first->agent != 0)
							//throw Error("Integrity error 1");

						list.clear();

						for (SpaceNode next = first->next; next != first; next = next->next)
						{
							if (next == 0)
								//throw Error("Integrity error 2");

							if (next->agent == 0)
								//throw Error("Integrity error 3");

							list.push_back(next);
						}

						int index = list.size() - 1;

						for (SpaceNode prev = first->prev; prev != first; prev = prev->prev)
						{
							if (prev == 0)
								//throw Error("Integrity error 4");

							if (prev->agent == 0)
								//throw Error("Integrity error 5");

							if (prev != list[index])
								//throw Error("Integrity error 6");

							index--;
						}
					}
			}*/

			double BoundedSpace::getXSize()
			{
				return xSize;
			}

			double BoundedSpace::getYSize()
			{
				return ySize;
			}

			double BoundedSpace::getXMin()
			{
				return xMin;
			}

			double BoundedSpace::getYMin()
			{
				return yMin;
			}

			double BoundedSpace::getXMax()
			{
				return xMax;
			}

			double BoundedSpace::getYMax()
			{
				return yMax;
			}

			bool BoundedSpace::getWrapX()
			{
				return wrapX;
			}

			bool BoundedSpace::getWrapY()
			{
				return wrapY;
			}

			BoundedSpace::BoundedSpace(double xMin, double xMax, double yMin, double yMax, bool wrapX, bool wrapY) : xMin(xMin), xMax(xMin + 1), yMin(yMin), yMax(yMin + 1), xSize(xMax - xMin), ySize(yMax - yMin)
			{
				//nodes = new ArrayList<SpaceNode>(100);

				if (xMax < xMin)
				if (yMax < yMin)
			
				this->xMax = xMax;
				this->yMax = yMax;
				this->wrapX = wrapX;
				this->wrapY = wrapY;

			}

			org::spark::math::Vector *BoundedSpace::getVector(Vector *v1, Vector *v2)
			{
				double dx = v2->x - v1->x;
				double dy = v2->y - v1->y;

				if (wrapX)
				{
					double dx2 = dx;
					if (dx > 0)
						dx2 -= getXSize();
					else
						dx2 += getXSize();

					if (abs(dx2) < abs(dx))
						dx = dx2;
				}

				if (wrapY)
				{
					double dy2 = dy;
					if (dy > 0)
						dy2 -= getYSize();
					else
						dy2 += getYSize();

					if (abs(dy2) < abs(dy))
						dy = dy2;
				}

				return new Vector(dx, dy, 0);
			}

			org::spark::math::Vector *BoundedSpace::getRandomPosition()
			{
				return new Vector(RandomHelper::random() * getXSize() + xMin, RandomHelper::random() * getYSize() + yMin, 0);
			}

			double BoundedSpace::restrictX(double x)
			{
				if (wrapX)
				{
					if (x < xMin)
					{
						x += xSize;
						if (x < xMin)
							x += (floor((xMin - x) / xSize) + 1) * xSize;
					}
					else if (x >= xMax)
					{
						x -= xSize;
						if (x >= xMax)
							x -= (floor((x - xMax) / xSize) + 1) * xSize;
					}
				}
				else
				{
					if (x < xMin)
						x = xMin;
					else if (x > xMax)
						x = xMax;
				}

				return x;
			}

			double BoundedSpace::restrictY(double y)
			{
				if (wrapY)
				{
					if (y < yMin)
					{
						y += ySize;
						if (y < yMin)
							y += (floor((yMin - y) / ySize) + 1) * ySize;
					}
					else if (y >= yMax)
					{
						y -= ySize;
						if (y >= yMax)
							y -= (floor((y - yMax) / ySize) + 1) * ySize;
					}
				}
				else
				{
					if (y < yMin)
						y = yMin;
					else if (y > yMax)
						y = yMax;
				}

				return y;
			}
		}
	}
}
